﻿using System;
using System.Collections.Generic;
using System.Net;
using HtmlAgilityPack;


namespace CCPSIP
{
    public class IPPbxKitV3
    {
        private const string kIPPbxVersion = "v3.0.2.2";
        private const string kDefaultServer = "118.163.125.205";
        private static System.Text.Encoding PageEncoding = System.Text.Encoding.GetEncoding(950);//Big5
        private static WebProxy DefaultProxy = new WebProxy("203.69.132.67", 8080);


        public static string[] GetUserList()
        {
            string targetPage = string.Format("https://{0}/usrlist.php", kDefaultServer);

            HtmlDocument htmlDoc = new HtmlDocument();
            htmlDoc.LoadHtml(GetWebHtml(targetPage));

            HtmlNodeCollection aNodes = htmlDoc.DocumentNode.SelectNodes("//a");
            List<string> phoneList = new List<string>();
            foreach (HtmlNode aNode in aNodes)
            {
                string hyperlink = aNode.Attributes["href"].Value;
                if (hyperlink.StartsWith("usrch.php?phone="))
                    phoneList.Add(hyperlink.Replace("usrch.php?phone=", ""));
            }
            return phoneList.ToArray();
        }


        public static bool HadUser(string phoneNumber)
        {
            foreach (string userPhone in GetUserList())
            {
                if (phoneNumber == userPhone)
                    return true;
            }
            return false;
        }


        public static Dictionary<string, string> GetDefaultParamDict(string serverAddr)
        {
            string targetPage = string.Format("https://{0}/usradd.php", serverAddr);

            HtmlDocument htmlDoc = new HtmlDocument();
            htmlDoc.LoadHtml(GetWebHtml(targetPage));

            HtmlNodeCollection paramNodes = htmlDoc.DocumentNode.SelectNodes("//input | //select");
            if (paramNodes == null)
            {
                throw new Exception("Error: PARAM_NODE_NOT_FOUND");
            }
            else if (paramNodes.Count < 25)
            {
                throw new Exception("Error: PARAM_NODE_NOT_ENOUGH");
            }

            Dictionary<string, string> paramDict = new Dictionary<string, string>();
            foreach (HtmlNode paramNode in paramNodes)
            {
                if (paramNode.Name == "input")
                {
                    if (paramNode.Attributes.Contains("type"))
                    {
                        string inputType = paramNode.Attributes["type"].Value;
                        if (inputType == "Submit" || inputType == "reset")
                            continue;
                    }
                    if (paramNode.Attributes.Contains("name"))
                    {
                        string paramName = paramNode.Attributes["name"].Value;

                        if (paramNode.Attributes.Contains("value"))
                            paramDict[paramName] = paramNode.Attributes["value"].Value;
                        else
                            paramDict[paramName] = "";
                    }
                }
                else if (paramNode.Name == "select")
                {
                    HtmlNode selectedNode = paramNode.SelectSingleNode("option[@selected]");
                    if (selectedNode == null)
                    {
                        selectedNode = paramNode.SelectSingleNode("option");
                    }
                    string paramName = paramNode.Attributes["name"].Value;
                    string paramValue = selectedNode.Attributes["value"].Value;
                    paramDict[paramName] = paramValue;
                }
            }
            paramDict.Remove("OK");
            return paramDict;
        }


        public static Dictionary<string, string> GetUserData(string phoneNumber)
        {
            string targetPage = string.Format("https://{0}/usrch.php?phone={1}", kDefaultServer, phoneNumber);

            HtmlDocument htmlDoc = new HtmlDocument();
            htmlDoc.LoadHtml(GetWebHtml(targetPage));

            HtmlNodeCollection paramNodes = htmlDoc.DocumentNode.SelectNodes("//input | //select");
            if (paramNodes == null)
            {
                throw new Exception("Error: PARAM_NODE_NOT_FOUND");
            }
            else if (paramNodes.Count < 44)
            {
                throw new Exception("Error: PARAM_NODE_NOT_ENOUGH");
            }

            Dictionary<string, string> paramDict = new Dictionary<string, string>();
            foreach (HtmlNode paramNode in paramNodes)
            {
                if (paramNode.Name == "input")
                {
                    if (paramNode.Attributes.Contains("type"))
                    {
                        string inputType = paramNode.Attributes["type"].Value;
                        if (inputType == "Submit" || inputType == "reset")
                            continue;
                    }
                    if (paramNode.Attributes.Contains("name"))
                    {
                        string paramName = paramNode.Attributes["name"].Value;

                        if (paramNode.Attributes.Contains("value"))
                            paramDict[paramName] = paramNode.Attributes["value"].Value;
                        else
                            paramDict[paramName] = "";
                    }
                }
                else if (paramNode.Name == "select")
                {
                    HtmlNode selectedNode = paramNode.SelectSingleNode("option[@selected]");
                    if (selectedNode == null)
                    {
                        selectedNode = paramNode.SelectSingleNode("option");
                    }
                    string paramName = paramNode.Attributes["name"].Value;
                    string paramValue = selectedNode.Attributes["value"].Value;
                    paramDict[paramName] = paramValue;
                }
            }
            paramDict.Remove("OK");
            return paramDict;
        }


        public static string AddUser(Dictionary<string, string> paramDict)
        {
            string targetPage = string.Format("https://{0}/usradd.php", kDefaultServer);

            HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create(targetPage);
            ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
            webReq.ProtocolVersion = HttpVersion.Version11;
            webReq.Method = "POST";
            webReq.Timeout = 30 * 1000;
            webReq.KeepAlive = false;
            webReq.AllowAutoRedirect = false;
            webReq.Proxy = DefaultProxy;
            webReq.ContentType = "application/x-www-form-urlencoded; charset=Big5";

            paramDict["OK"] = "YES";
            paramDict["send"] = "確定";
            string paramStr = ChrisKit.DictToQueryStr(paramDict, PageEncoding);

            byte[] postBytes = PageEncoding.GetBytes(paramStr);
            webReq.ContentLength = postBytes.Length;
            using (System.IO.Stream reqStream = webReq.GetRequestStream())
            {
                reqStream.Write(postBytes, 0, postBytes.Length);
                reqStream.Flush();
                reqStream.Close();
            }
            HttpWebResponse webResp = (HttpWebResponse)webReq.GetResponse();
            webResp.Close();

            // 2014/11/06
            // 檢查使用者資料是否真的新增到IPPBX Server上, 才能回傳"OK"
            Dictionary<string, string> newUserData = GetUserData(paramDict["name"]);
            if (String.IsNullOrEmpty(newUserData["name"]))
                throw new Exception("Add User to IPPBX failed. Please check the IPPBX webserver status.");
            else
                return "OK";
        }

        /// <summary>刪除IPPBX帳號(內部 or 外部)</summary>
        /// <param name="phoneNumber">IP電話號碼</param>
        /// <returns>刪除成功or失敗</returns>
        public static bool DeleteUser(string PhoneNumber)
        {
            //【01】檢查PhoneNumber是否存在
            if (!HadUser(PhoneNumber))
                return false;

            //【02】刪除PhoneNumber
            string TargetPage = string.Format("https://{0}/usrrm.php", kDefaultServer);
            HttpWebRequest WebReq = (HttpWebRequest)WebRequest.Create(TargetPage);
            ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

            WebReq.ProtocolVersion = HttpVersion.Version11;
            WebReq.Method = "POST";
            WebReq.Timeout = 30 * 1000;
            WebReq.KeepAlive = false;
            WebReq.AllowAutoRedirect = false;
            WebReq.Proxy = DefaultProxy;
            WebReq.ContentType = "application/x-www-form-urlencoded; charset=Big5";

            Dictionary<string, string> paramDict = new Dictionary<string, string>();
            paramDict["OK"] = "YES";
            paramDict["phone"] = PhoneNumber;
            paramDict["send"] = "確定";
            string paramStr = ChrisKit.DictToQueryStr(paramDict, PageEncoding);

            byte[] postBytes = PageEncoding.GetBytes(paramStr);
            WebReq.ContentLength = postBytes.Length;
            using (System.IO.Stream reqStream = WebReq.GetRequestStream())
            {
                reqStream.Write(postBytes, 0, postBytes.Length);
                reqStream.Flush();
                reqStream.Close();
            }

            HttpWebResponse webResp = (HttpWebResponse)WebReq.GetResponse();
            webResp.Close();

            //【03】檢查是否刪除成功
            if (!HadUser(PhoneNumber))
                return true;
            else
                return false;
        }


        public static string UpdateUser(Dictionary<string, string> paramDict)
        {
            string targetPage = string.Format("https://{0}/usrch.php", kDefaultServer);

            HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create(targetPage);
            ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
            webReq.ProtocolVersion = HttpVersion.Version11;
            webReq.Method = "POST";
            webReq.Timeout = 30 * 1000;
            webReq.KeepAlive = false;
            webReq.AllowAutoRedirect = false;
            webReq.Proxy = DefaultProxy;
            webReq.ContentType = "application/x-www-form-urlencoded; charset=Big5";

            paramDict["OK"] = "YES";
            paramDict["send"] = "確定";
            string paramStr = ChrisKit.DictToQueryStr(paramDict, PageEncoding);

            byte[] postBytes = PageEncoding.GetBytes(paramStr);
            webReq.ContentLength = postBytes.Length;
            using (System.IO.Stream reqStream = webReq.GetRequestStream())
            {
                reqStream.Write(postBytes, 0, postBytes.Length);
                reqStream.Flush();
                reqStream.Close();
            }
            HttpWebResponse webResp = (HttpWebResponse)webReq.GetResponse();
            webResp.Close();

            // 2014/11/06
            // 檢查使用者密碼是否真的從IPPBX Server上更新, 才能回傳"OK"
            string password_after_update = GetUserData(paramDict["name"])["password"];
            if (string.Equals(password_after_update, paramDict["password"]))
                return "OK";
            else
                throw new Exception("Update User to IPPBX failed. Please check the IPPBX webserver status.");
        }


        private static string GetWebHtml(string webUrl)
        {
            const int kRespMaxKB = 3000;//in KB
            try
            {
                HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create(webUrl);
                ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
                webReq.ProtocolVersion = HttpVersion.Version11;
                webReq.Method = "GET";
                webReq.Timeout = 30 * 1000;
                webReq.KeepAlive = false;
                webReq.AllowAutoRedirect = false;
                webReq.Proxy = DefaultProxy;

                HttpWebResponse webResp = (HttpWebResponse)webReq.GetResponse();
                System.IO.Stream respStream = webResp.GetResponseStream();
                byte[] pageBytes = new byte[kRespMaxKB * 1024];
                int bytesCount = 0;

                for (int i = 0; i < kRespMaxKB; i++)
                {
                    int readCount = respStream.Read(pageBytes, bytesCount, 1024);
                    if (readCount == 0)
                        break;
                    else
                        bytesCount += readCount;
                }
                respStream.Close();
                webResp.Close();

                return PageEncoding.GetString(pageBytes, 0, bytesCount);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }


        public static string getPropertyCName(string PropertyName)
        {
            if (PropertyName == "phone")
                return "帳號";
            else if (PropertyName == "name")
                return "英文名稱";
            else if (PropertyName == "name_cn")
                return "中文名稱";
            else if (PropertyName == "mobile")
                return "行動電話";
            else if (PropertyName == "enterprise")
                return "公司";
            else if (PropertyName == "unit")
                return "部門";
            else if (PropertyName == "host")
                return "IP位址";
            else if (PropertyName == "secret")
                return "登入密碼";
            else if (PropertyName == "callgroup")
                return "代接群";
            else if (PropertyName == "provision")
                return "自動供裝";
            else if (PropertyName == "mwi")
                return "訊息等待指示";
            else if (PropertyName == "rcd_cg")
                return "啟動主叫錄音";
            else if (PropertyName == "rcd_cd")
                return "啟動被叫錄音";
            else if (PropertyName == "video")
                return "視訊通話";
            else if (PropertyName == "dtmf")
                return "DTMF型態";
            else if (PropertyName == "nat")
                return "NAT";
            else if (PropertyName == "tls")
                return "TLS連線";
            else if (PropertyName == "phoneset")
                return "帳號啟用";
            else if (PropertyName == "password")
                return "網頁密碼";
            else if (PropertyName == "codec1")
                return "編碼器1";
            else if (PropertyName == "codec2")
                return "編碼器2";
            else if (PropertyName == "codec3")
                return "編碼器3";
            else if (PropertyName == "codec4")
                return "編碼器4(audio)";
            else if (PropertyName == "codec5")
                return "編碼器5(audio)";
            else if (PropertyName == "cos")
                return "服務等級";
            else if (PropertyName == "pincode")
                return "通行碼";
            else if (PropertyName == "cfphone")
                return "指定轉接";
            else if (PropertyName == "cfbphone")
                return "忙線轉接";
            else if (PropertyName == "cfnphone")
                return "無應答轉接";
            else if (PropertyName == "forkphone1")
                return "共振號碼1";
            else if (PropertyName == "forkphone2")
                return "共振號碼2";
            else if (PropertyName == "forkphone3")
                return "共振號碼3";
            else if (PropertyName == "email")
                return "郵件位址";
            else if (PropertyName == "v2e")
                return "信箱留言通知";
            else if (PropertyName == "rmvm")
                return "通知後刪除留言";

            return PropertyName;
        }

    }
}